package com.example.lib.muchthread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class q_producer_consumer_jdk5_147 {
    public static void main(String[] args) {
        Resource147 res = new Resource147();

        Producer147 product = new Producer147(res);
        Consumer147 consumer = new Consumer147(res);

        Thread t1 = new Thread(product);
        Thread t2 = new Thread(product);
        Thread t3 = new Thread(consumer);
        Thread t4 = new Thread(consumer);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

/**
 * JDK1.5中提供了多线程升级的解决方案。
 * 将同步synchronized替换成显示Lock操作。
 * 将Object中的wait，notify，notifyAll,替换成了Condition对象。
 * 该对象可以通过Lock锁进行获取。
 * 该示例中，实现了本方只唤醒对方的操作。
 */

class Resource147 {
    private String name;
    private int count = 1;
    private boolean flag = false;

    private Lock lock=new ReentrantLock();

    private Condition condition_pro=lock.newCondition();
    private Condition condition_con=lock.newCondition();

    public void set(String name) throws InterruptedException{
        lock.lock();
        try {
            if (flag) {
                condition_pro.await();
            }
            this.name = name + "--" + count++;
            System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
            flag = true;
            condition_con.signal();
        }finally {
            lock.unlock();
        }
    }

    public synchronized void out() throws InterruptedException{
        lock.lock();
        try {
            if (!flag) {
                condition_con.await();
            }
            System.out.println(Thread.currentThread().getName() + "...消费者......"+this.name);
            flag = false;
            condition_pro.signal();
        }finally {
            lock.unlock();
        }
    }
}

class Producer147 implements Runnable {

    private Resource147 res;

    public Producer147(Resource147 res) {
        this.res = res;
    }

    @Override
    public void run() {
        try {
            while (true) {
                res.set("+商品+");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}

class Consumer147 implements Runnable {

    private Resource147 res;

    public Consumer147(Resource147 res) {
        this.res = res;
    }

    @Override
    public void run() {
        try {
            while (true) {
                res.out();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}